package com.example.personal.aiagent.user.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.example.personal.aiagent.common.constant.ErrorCode;
import com.example.personal.aiagent.user.model.entity.UserEntity;
import com.example.personal.aiagent.xunfei.account.mapper.AccountMapper;
import com.example.personal.aiagent.xunfei.account.model.dto.AccountDTO;
import com.example.personal.aiagent.xunfei.account.model.entity.AccountEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import com.example.personal.aiagent.common.exception.CustomServiceException;
import com.example.personal.aiagent.user.mapper.UserMapper;
import com.example.personal.aiagent.user.model.dto.UserDTO;

import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户服务层
 */
@Service
@Slf4j
public class UserServiceAbility implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AccountMapper accountMapper;

    @Override
    public void insertUser(UserDTO userDTO) {
        log.info("insert user:{}", userDTO.getUsername());
        if (selectByUsername(userDTO.getUsername()) != null) {
            throw new CustomServiceException(ErrorCode.USER_EXISTS);
        }
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        int res = userMapper.insertUser(userDTO.getUsername(), "{bcrypt}" + encoder.encode(userDTO.getPassword()));
        if (res != 1) {
            throw new CustomServiceException("insert user");
        }
    }

    @Override
    public void updateUser(UserDTO userDTO) {
        log.info("update user, id:{}, username:{}", userDTO.getId(), userDTO.getUsername());
        if (userMapper.selectById(userDTO.getId()) == null) {
            throw new CustomServiceException(ErrorCode.USER_NOT_EXIST);
        }
        int res = userMapper.updateUser(userDTO.getId(), userDTO.getUsername(), userDTO.getPassword());
        if (res != 1) {
            throw new CustomServiceException("update user");
        }
    }

    @Override
    public void deleteById(int id) {
        log.info("delete user id:{}", id);
        if (userMapper.selectById(id) == null) {
            throw new CustomServiceException(ErrorCode.USER_NOT_EXIST);
        }
        int res = userMapper.deleteById(id);
        if (res != 1) {
            log.warn("no user found");
        }
    }

    @Override
    public UserDTO selectByUsername(String username) {
        UserEntity user = userMapper.selectByUsername(username);
        AccountEntity account = null;
        if (user != null) {
            account = accountMapper.selectByUserId(user.getId());
        }
        return UserDTO.entityToDTO(user, account);
    }

    @Override
    public IPage<UserDTO> selectUsers(IPage<UserDTO> page, Integer id, String username) {
        IPage<UserEntity> query = new PageDTO<>();
        query.setSize(page.getSize());
        query.setCurrent(page.getCurrent());
        IPage<UserEntity> entities = userMapper.selectUsers(query, id, username);
        IPage<UserDTO> res = new PageDTO<>();
        res.setSize(entities.getSize());
        res.setCurrent(entities.getCurrent());
        res.setPages(entities.getPages());
        res.setTotal(entities.getTotal());
        Map<Integer, AccountEntity> accounts = accountMapper.selectByUserIds(entities.getRecords().stream().map(
            UserEntity::getId).collect(Collectors.toList()));
        res.setRecords(entities.getRecords().stream().map(it -> {
            UserDTO user = UserDTO.entityToDTO(it);
            user.setAccountDTO(AccountDTO.entityToDTO(accounts.get(it.getId())));
            return user;
        }).collect(Collectors.toList()));
        return res;
    }
}
